package com.example.custsecurity.security.filter;

import com.alibaba.fastjson.JSONObject;
import com.example.custsecurity.security.jwt.CustJwtService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/*
 * UsernamePasswordAuthenticationFilter：过滤用户输入的账号与密码
 * 注：该过滤器只在登录时使用 只在登录时拦截一次
 * 注：登录时的表单数据账号和密码  只能使用username和password作为name的属性值
 * 注：过滤器中会默认访问/login路径作为登录表单提交的路径
 * 注：如果使用自定义的登录表单提交路径 则需手动指定访问路径，否则该拦截器失效
 * */

@Slf4j
public class CustLoginJWTTokenFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;
    private CustJwtService custJwtService;

    public CustLoginJWTTokenFilter(CustJwtService custJwtService, AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        this.custJwtService = custJwtService;
//        手动指定登陆表单提交路径
        this.setFilterProcessesUrl("/logingprocess");
    }

    @SneakyThrows
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        log.debug("........账号" + request.getParameter("username") + ".......密码" + request.getParameter("password"));
//        return super.attemptAuthentication(request, response);

        String head_token = request.getHeader("Authentication");

//        获取用户名和密码
        String username = this.obtainUsername(request);
        String password = this.obtainPassword(request);

//        如果登录时携带token
        if (head_token == null) {

            return
                    this.authenticationManager
                            .authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } else {
                Map<String, Object> map = null;
                try {

                    map = this.custJwtService.verifyJWTToken(head_token);
                } catch (RuntimeException e) {
                    throw new BadCredentialsException("token验证出错" + e.getLocalizedMessage());
                    /*response.setCharacterEncoding("utf-8");
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter pw = response.getWriter();

                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                    jsonObject.put("msg", "token验证出错" + e.getLocalizedMessage());

                    pw.print(jsonObject);
                    pw.flush();
                    pw.close();*/

                }
                String account = map.get("account").toString();
                String role = map.get("role").toString();
                String[] roles = role.split("");
                List<GrantedAuthority> list = new ArrayList<>();
                for (int i = 0; i < roles.length; i++) {
                    list.add(new SimpleGrantedAuthority(roles[i]));
                }

                //        获取登录时传递过来的用户名和密码  authenticate方法的参数实际就是用户名和密码
                return
                    this.authenticationManager
                            .authenticate(new UsernamePasswordAuthenticationToken(username, password, list));
        }
    }
}
